﻿/****************************************************
	文件：MsgBase.cs
	作者：HuskyT
	邮箱:  1005240602@qq.com
	日期：2020/04/26 15:34   	
	功能：网络消息工具类（用于编码、解码 网络消息）
*****************************************************/

using System;
using System.Text;
using ProtoBuf;
using System.IO;
using HTServer.Proto;
using System.Reflection;

namespace HTServer.Net
{
    public class MsgTools
    {
        /// <summary>
        /// 编码协议名
        /// </summary>
        public static byte[] EncodeName(MsgBase msg)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(msg.ProtoType.ToString());//协议名
            //在字节数组中：前两字节存储协议名的长度（使用int16）
            Int16 len = (Int16)bytes.Length;
            byte[] ret = new byte[2 + len];
            ret[0] = (byte)(len / 256);//第一个字节存储除后的结果
            ret[1] = (byte)(len % 256);//第二个字节存储余数
            Array.Copy(bytes, 0, ret, 2, len);
            return ret;
        }
        /// <summary>
        /// 解码协议名
        /// </summary>
        public static ProtoEnum DecodeName(byte[] bytes, int offset, out int length)
        {
            length = 0;
            if (offset + 2 > bytes.Length) return ProtoEnum.None;
            Int16 len = (Int16)(bytes[offset] << 8 | bytes[offset + 1]);//结果乘以256加余数
            if (offset + 2 + len > bytes.Length) return ProtoEnum.None;//协议名有问题
            length = 2 + len;
            try
            {
                string protoTypeStr = Encoding.UTF8.GetString(bytes, offset + 2, len);
                return (ProtoEnum)Enum.Parse(typeof(ProtoEnum), protoTypeStr);
            }
            catch (Exception e)
            {
                Debug.LogError("解码协议名出错：{0}", e.ToString());
                return ProtoEnum.None;
            }
        }

        /// <summary>
        /// 编码协议数据（协议的序列化及加密）
        /// </summary>
        public static byte[] Encode(MsgBase msg)
        {
            using (MemoryStream memory = new MemoryStream())
            {
                Serializer.Serialize(memory, msg);//ProtoBuf的序列化
                byte[] bytes = memory.ToArray();
                //加密
                string key = Server.SecretKey;
                if (msg is MsgSecret)
                {
                    key = Server.PublicKey;//使用秘钥协议的时候使用的是公钥加密
                }
                bytes = AES.AESEncrypt(bytes, key);
                return bytes;
            }
        }
        /// <summary>
        /// 解码协议数据（协议的解密及反序列化）
        /// </summary>
        public static MsgBase Decode(ProtoEnum protoType, byte[] bytes, int offset, int count)
        {
            if (count <= 0)
            {
                Debug.LogError("解码协议出错，协议数据长度为0！");
                return null;
            }
            try
            {
                byte[] data = new byte[count];
                Array.Copy(bytes, offset, data, 0, count);
                string key = Server.SecretKey;//秘钥
                if (protoType == ProtoEnum.MsgSecret)
                {
                    key = Server.PublicKey;
                }
                data = AES.AESDecrypt(data, key);//解密
                using (MemoryStream memory = new MemoryStream(data, 0, data.Length))
                {
                    Type t = Type.GetType("HTServer.Proto." + protoType.ToString());
                    return (MsgBase)Serializer.NonGeneric.Deserialize(t, memory);//ProtoBuf的反序列化
                }
            }
            catch (Exception e)
            {
                Debug.LogError("解码协议出错：{0}", e.ToString());
                return null;
            }
        }

    }
}